break;
+ case BLKIF_INTERFACE_STATUS_CHANGED:
+ /* The domain controller is notifying us that a device has been
+ * added or removed.
+ */
+ break;
+
default:
printk(KERN_WARNING "Status change to unknown value %d\n",
status->status);
vif_wake(dev);
break;
+ case NETIF_INTERFACE_STATUS_CHANGED:
+ /* The domain controller is notifying us that a device has been
+ * added or removed.
+ */
+ break;
+
default:
printk(KERN_WARNING "Status change to unknown value %d\n",
status->status);
return self.xendPost(self.domainurl(id),
{'op' : 'device_destroy',
'type' : type,
- 'index' : idx })
+ 'idx' : idx })
def xend_consoles(self):
return self.xendGet(self.consoleurl())
dl.append(dev)
self.devices[type] = dl
+ def remove_device(self, type, dev):
+ """Remove a device from a virtual machine.
+
+ @param type: device type
+ @param dev: device
+ """
+ dl = self.devices.get(type, [])
+ if dev in dl:
+ dl.remove(dev)
+
def get_devices(self, type):
"""Get a list of the devices of a given type.
devs = self.get_devices(dev_name)
dev_index = len(devs)
self.config.append(['device', dev_config])
- d = dev_handler(self, dev_config, dev_index)
+ d = dev_handler(self, dev_config, dev_index, change=1)
return d
def device_destroy(self, type, idx):
dev_config = self.config_device(type, index)
if dev_config:
self.config.remove(['device', dev_config])
- dev.destroy()
+ dev.destroy(change=1)
+ self.remove_device(type, dev)
def configure_memory(self):
"""Configure vm memory limit.
return vm
-def vm_dev_vif(vm, val, index):
+def vm_dev_vif(vm, val, index, change=0):
"""Create a virtual network interface (vif).
@param vm: virtual machine
def cbok(dev):
dev.vifctl('up', vmname=vm.name)
vm.add_device('vif', dev)
+ if change:
+ dev.interfaceChanged()
return dev
defer.addCallback(cbok)
return defer
-def vm_dev_vbd(vm, val, index):
+def vm_dev_vbd(vm, val, index, change=0):
"""Create a virtual block device (vbd).
@param vm: virtual machine
vbd.dev = dev
vbd.uname = uname
vm.add_device('vbd', vbd)
+ if change:
+ vbd.interfaceChanged()
return vbd
defer.addCallback(fn)
return defer
v = val
return v
-def vm_dev_pci(vm, val, index):
+def vm_dev_pci(vm, val, index, change=0):
"""Add a pci device.
@param vm: virtual machine
"""
from twisted.internet import defer
-#defer.Deferred.debug = 1
from xen.xend import sxp
from xen.xend.XendLogging import log
self.send_be_disconnect(response=d)
def send_be_disconnect(self, response=None):
- log.debug('>BlkifBackendController>send_be_disconnect> %s', str(self))
msg = packMsg('blkif_be_disconnect_t',
{ 'domid' : self.controller.dom,
'blkif_handle' : self.handle })
self.writeRequest(msg, response=response)
def send_be_destroy(self, response=None):
- log.debug('>BlkifBackendController>send_be_destroy> %s', str(self))
msg = packMsg('blkif_be_destroy_t',
{ 'domid' : self.controller.dom,
'blkif_handle' : self.handle })
msg = packMsg('blkif_fe_interface_status_changed_t',
{ 'handle' : self.handle,
'status' : BLKIF_INTERFACE_STATUS_CONNECTED,
- 'domid' : 0, ## FIXME: should be domid of backend
+ 'domid' : self.dom,
'evtchn' : self.evtchn['port2'] })
self.controller.writeRequest(msg, response=response)
+
+ def interfaceDisconnected(self):
+ msg = packMsg('blkif_fe_interface_status_changed_t',
+ { 'handle' : self.handle,
+ 'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED,
+ 'domid' : self.dom,
+ 'evtchn' : 0 })
+ self.controller.writeRequest(msg)
+
+ def interfaceChanged(self):
+ """Notify the front-end that devices have been added or removed.
+ The front-end should then probe for devices.
+ """
+ msg = packMsg('blkif_fe_interface_status_changed_t',
+ { 'handle' : self.handle,
+ 'status' : BLKIF_INTERFACE_STATUS_CHANGED,
+ 'domid' : self.dom,
+ 'evtchn' : 0 })
+ self.controller.writeRequest(msg)
class BlkifControllerFactory(controller.SplitControllerFactory):
"""Factory for creating block device interface controllers.
val.append(['uname', self.uname])
return val
- def destroy(self):
+ def destroy(self, change=0):
+ """Destroy the device. If 'change' is true notify the front-end interface.
+
+ @param change: change flag
+ """
log.debug("Destroying vbd domain=%d vdev=%d", self.controller.dom, self.vdev)
- self.send_be_vbd_destroy()
+ d = self.send_be_vbd_destroy()
+ if change:
+ d.addCallback(lambda val: self.interfaceChanged())
+
+ def interfaceChanged(self):
+ """Tell the back-end to notify the front-end that a device has been
+ added or removed.
+ """
+ self.getBackendInterface().interfaceChanged()
def attach(self):
"""Attach the device to its controller.
% (self.vdev, status))
return self
- def send_be_vbd_destroy(self, response=None):
- log.debug('>BlkDev>send_be_vbd_destroy> dom=%d vdev=%d',
- self.controller.dom, self.vdev)
+ def send_be_vbd_destroy(self):
+ d = defer.Deferred()
backend = self.getBackendInterface()
msg = packMsg('blkif_be_vbd_destroy_t',
{ 'domid' : self.controller.dom,
'blkif_handle' : backend.handle,
'vdevice' : self.vdev })
self.controller.delDevice(self.vdev)
- backend.writeRequest(msg, response=response)
+ backend.writeRequest(msg, response=d)
+ return d
class BlkifController(controller.SplitController):
def recv_fe_driver_status_changed(self, msg, req):
val = unpackMsg('blkif_fe_driver_status_changed_t', msg)
- # For each backend?
- msg = packMsg('blkif_fe_interface_status_changed_t',
- { 'handle' : 0,
- 'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED,
- 'domid' : 0, ## FIXME: should be domid of backend
- 'evtchn' : 0 })
- self.writeRequest(msg)
+ for backend in self.getBackendInterfaces():
+ backend.interfaceDisconnected()
def recv_fe_interface_connect(self, msg, req):
val = unpackMsg('blkif_fe_interface_connect_t', msg)
BLKIF_INTERFACE_STATUS_DESTROYED = 0 #/* Interface doesn't exist. */
BLKIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
BLKIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */
+BLKIF_INTERFACE_STATUS_CHANGED = 3 #/* A device has been added or removed. */
BLKIF_BE_STATUS_OKAY = 0
BLKIF_BE_STATUS_ERROR = 1
NETIF_INTERFACE_STATUS_DESTROYED = 0 #/* Interface doesn't exist. */
NETIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
NETIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */
+NETIF_INTERFACE_STATUS_CHANGED = 3 #/* A device has been added or removed. */
NETIF_DRIVER_STATUS_DOWN = 0
NETIF_DRIVER_STATUS_UP = 1
import random
from twisted.internet import defer
-#defer.Deferred.debug = 1
from xen.xend import sxp
from xen.xend import Vifctl
val = unpackMsg('netif_be_create_t', msg)
return self
- def destroy(self):
+ def destroy(self, change=0):
"""Destroy the device's resources and disconnect from the back-end
- device controller.
+ device controller. If 'change' is true notify the front-end interface.
+
+ @param change: change flag
"""
def cb_destroy(val):
self.send_be_destroy()
self.getBackendInterface().close()
+ if change:
+ self.interfaceChanged()
log.debug("Destroying vif domain=%d vif=%d", self.controller.dom, self.vif)
self.vifctl('down')
d = self.send_be_disconnect()
{ 'handle' : self.vif,
'status' : NETIF_INTERFACE_STATUS_CONNECTED,
'evtchn' : self.evtchn['port2'],
- 'domid' : 0, ## FIXME: should be domid of backend
+ 'domid' : self.backendDomain,
'mac' : self.mac })
self.controller.writeRequest(msg)
{ 'handle' : self.vif,
'status' : NETIF_INTERFACE_STATUS_DISCONNECTED,
'evtchn' : 0,
- 'domid' : 0, ## FIXME: should be domid of backend
+ 'domid' : self.backendDomain,
+ 'mac' : self.mac })
+ self.controller.writeRequest(msg)
+
+ def interfaceChanged(self):
+ """Notify the font-end that a device has been added or removed.
+ The front-end should then probe the devices.
+ """
+ msg = packMsg('netif_fe_interface_status_changed_t',
+ { 'handle' : self.vif,
+ 'status' : NETIF_INTERFACE_STATUS_CHANGED,
+ 'evtchn' : 0,
+ 'domid' : self.backendDomain,
'mac' : self.mac })
self.controller.writeRequest(msg)
info = """Create a new virtual block device for a domain"""
def help(self, args):
- print args[0], "DOM UNAME DEV MODE"
+ print args[0], "DOM UNAME DEV MODE [BACKEND]"
print """
Create a virtual block device for a domain.
- UNAME - device to export, e.g. phys:hda2
- DEV - device name in the domain, e.g. xda1
- MODE - access mode: r for read, w for read-write
+ UNAME - device to export, e.g. phy:hda2
+ DEV - device name in the domain, e.g. xda1
+ MODE - access mode: r for read, w for read-write
+ BACKEND - backend driver domain
"""
def main(self, args):
- if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0])
+ n = len(args)
+ if n < 5 or n > 6: self.err("%s: Invalid argument(s)" % args[0])
dom = args[1]
vbd = ['vbd',
['uname', args[2]],
['dev', args[3]],
['mode', args[4]]]
+ if n == 6:
+ vbd.append(['backend', args[5]])
server.xend_domain_device_create(dom, vbd)
xm.prog(ProgVbdCreate)
print args[0], "DOM DEV"
print """
Destroy vbd DEV attached to domain DOM. Detaches the device
-from the domain, but does not destroy the device contents."""
+from the domain, but does not destroy the device contents.
+The device indentifier DEV is the idx field in the device
+information. This is visible in 'xm vbd-list'."""
def main(self, args):
- if len(args!=3): self.err("%s: Invalid argument(s)" % args[0])
+ if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
dom = args[1]
dev = args[2]
- sever.xend_domain_device_destroy(dom, "vbd", dev)
+ server.xend_domain_device_destroy(dom, "vbd", dev)
xm.prog(ProgVbdDestroy)
#define BLKIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist. */
#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
#define BLKIF_INTERFACE_STATUS_CONNECTED 2 /* Exists and is connected. */
+#define BLKIF_INTERFACE_STATUS_CHANGED 3 /* A device has been added or removed. */
typedef struct {
u32 handle; /* 0 */
u32 status; /* 4 */
#define NETIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist. */
#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
#define NETIF_INTERFACE_STATUS_CONNECTED 2 /* Exists and is connected. */
+#define NETIF_INTERFACE_STATUS_CHANGED 3 /* A device has been added or removed. */
typedef struct {
u32 handle; /* 0 */
u32 status; /* 4 */